﻿using MvvmCross.Core.Platform;
using MvvmCross.Core.ViewModels;
using MvvmCross.Platform;
using MvvmCross.Wpf.Platform;
using MvvmCross.Wpf.Views;
using System.Windows;
using System.Windows.Threading;

namespace Sidvall.UI.Wpf
{
    public abstract class ApplicationManager
    {
        #region Public Members

        #region OnActivated

        public void OnActivated(Application app)
        {
            if (Sidvall.UI.SystemContext.Current.ApplicationManager.Status == ApplicationStatus.NotInitialized)
                DoSetup(app);
        }

        #endregion

        // Protected
        #region RunAppStart

        protected virtual bool RunAppStart
        {
            get
            {
                return true;
            }
        }

        #endregion
        protected abstract void RegisterTypes();
        protected abstract MvxWpfSetup CreateSetup(Dispatcher uiThreadDispatcher, IMvxWpfViewPresenter presenter);
        #region GetExceptionFilePath

        protected virtual string GetExceptionFilePath()
        {
            return System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments), "Exception.txt");
        }

        #endregion
        #region GetMaxHistoryItemCount

        protected virtual int? GetMaxHistoryItemCount()
        {
            return 10;
        }

        #endregion
        #region OnInitialized

        protected virtual void OnInitialized()
        {
        }

        #endregion
        #region OnStarted

        protected virtual void OnStarted()
        {
        }

        #endregion

        #endregion
        #region Private Members

        #region AppDomainUnhandledException

        private void AppDomainUnhandledException(object sender, System.UnhandledExceptionEventArgs e)
        {
            HandleException(e.ExceptionObject as System.Exception);
        }

        #endregion
        #region DoSetup

        private void DoSetup(Application app)
        {
            // Preinitialize
            try
            {
                System.AppDomain.CurrentDomain.UnhandledException += AppDomainUnhandledException;
                RegisterTypes();
            }
            catch (System.Exception ex)
            {
                System.Windows.MessageBox.Show(GetErrorMessage(ex), "Exception - Preinitialize");
                Application.Current.Shutdown();
            }

            // Initializing
            try
            {
                Sidvall.UI.SystemContext.Current.ApplicationManager.Status = Sidvall.UI.ApplicationStatus.Initializing;
                Sidvall.UI.Wpf.SystemContext.Current.MainWindow = app.MainWindow;
                Sidvall.UI.SystemContext.Current.NavigationManager.MaxHistoryItemCount = GetMaxHistoryItemCount();
                var presenter = new Sidvall.UI.Wpf.Presenters.RegionPresenter();
                var setup = CreateSetup(app.Dispatcher, presenter);
                if (setup != null)
                {
                    setup.Initialize();
                    Sidvall.UI.EventManager.IsEnabled = true;
                }
                OnInitialized();
            }
            catch (System.Exception ex)
            {
                System.Windows.MessageBox.Show(GetErrorMessage(ex), "Exception - Initializing");
                Application.Current.Shutdown();
            }

            // Starting
            try
            {
                Sidvall.UI.SystemContext.Current.ApplicationManager.Status = Sidvall.UI.ApplicationStatus.Starting;
                if (this.RunAppStart)
                {
                    var start = Mvx.Resolve<IMvxAppStart>();
                    start.Start();
                }
                OnStarted();
                Sidvall.UI.SystemContext.Current.ApplicationManager.SetupCompleted = true;
            }
            catch (System.Exception ex)
            {
                System.Windows.MessageBox.Show(GetErrorMessage(ex), "Exception - Starting");
                Application.Current.Shutdown();
            }
        }

        #endregion
        #region GetErrorMessage

        private static string GetErrorMessage(System.Exception exception)
        {
            return GetErrorMessage(exception, System.Environment.NewLine, System.Environment.NewLine + System.Environment.NewLine);
        }
        private static string GetErrorMessage(System.Exception exception, string messageSeparator, string sectionSeparator)
        {
            var manager = new Sidvall.ExceptionHandling.SystemExceptionProvider();
            return manager.GetMessage(new System.Exception[] { exception }, messageSeparator, sectionSeparator);
        }

        #endregion
        #region HandleException

        private void HandleException(System.Exception ex)
        {
            string path;

            if (ex == null)
                return;

            var content = GetErrorMessage(ex);
            try
            {
                path = GetExceptionFilePath();
                System.IO.File.WriteAllText(path, content);
            }
            catch
            {
                path = null;
            }
            if (!string.IsNullOrWhiteSpace(path))
                content = "A log file has been created at \"" + path + "\"." + System.Environment.NewLine + System.Environment.NewLine + content;
            System.Windows.MessageBox.Show(content, "Unhandled Exception");
        }

        #endregion

        #endregion
    }
}
